#include <sstream>
#include "legendre.h"

void Legendre::p(unsigned d,
                 const mpfr_class & x,
                 std::vector<mpfr_class> & vals)
{
  // Make sure there are no old values in the vector.
  vals.clear();

  /* 0 */ vals.push_back(1);

  if (d >= 1)
    /* 1 */ vals.push_back(x);
  if (d >= 2)
    /* 2 */ vals.push_back(pow(x, 2) + (1.0/4.0)*pow(x - 1, 2) + (1.0/4.0)*pow(x + 1, 2) - 1);
  if (d >= 3)
    /* 3 */ vals.push_back((1.0/8.0)*pow(x - 1, 3) + (9.0/8.0)*pow(x - 1, 2)*(x + 1) + (9.0/8.0)*(x - 1)*pow(x + 1, 2) + (1.0/8.0)*pow(x + 1, 3));
  if (d >= 4)
    /* 4 */ vals.push_back((1.0/16.0)*pow(x - 1, 4) + pow(x - 1, 3)*(x + 1) + (9.0/4.0)*pow(x - 1, 2)*pow(x + 1, 2) + (x - 1)*pow(x + 1, 3) + (1.0/16.0)*pow(x + 1, 4));
  if (d >= 5)
    /* 5 */ vals.push_back((1.0/32.0)*pow(x - 1, 5) + (25.0/32.0)*pow(x - 1, 4)*(x + 1) + (25.0/8.0)*pow(x - 1, 3)*pow(x + 1, 2) + (25.0/8.0)*pow(x - 1, 2)*pow(x + 1, 3) + (25.0/32.0)*(x - 1)*pow(x + 1, 4) + (1.0/32.0)*pow(x + 1, 5));
  if (d >= 6)
    /* 6 */ vals.push_back((1.0/64.0)*pow(x - 1, 6) + (9.0/16.0)*pow(x - 1, 5)*(x + 1) + (225.0/64.0)*pow(x - 1, 4)*pow(x + 1, 2) + (25.0/4.0)*pow(x - 1, 3)*pow(x + 1, 3) + (225.0/64.0)*pow(x - 1, 2)*pow(x + 1, 4) + (9.0/16.0)*(x - 1)*pow(x + 1, 5) + (1.0/64.0)*pow(x + 1, 6));
  if (d >= 7)
    /* 7 */ vals.push_back((1.0/128.0)*pow(x - 1, 7) + (49.0/128.0)*pow(x - 1, 6)*(x + 1) + (441.0/128.0)*pow(x - 1, 5)*pow(x + 1, 2) + (1225.0/128.0)*pow(x - 1, 4)*pow(x + 1, 3) + (1225.0/128.0)*pow(x - 1, 3)*pow(x + 1, 4) + (441.0/128.0)*pow(x - 1, 2)*pow(x + 1, 5) + (49.0/128.0)*(x - 1)*pow(x + 1, 6) + (1.0/128.0)*pow(x + 1, 7));
  if (d >= 8)
    /* 8 */ vals.push_back((1.0/256.0)*pow(x - 1, 8) + (1.0/4.0)*pow(x - 1, 7)*(x + 1) + (49.0/16.0)*pow(x - 1, 6)*pow(x + 1, 2) + (49.0/4.0)*pow(x - 1, 5)*pow(x + 1, 3) + (1225.0/64.0)*pow(x - 1, 4)*pow(x + 1, 4) + (49.0/4.0)*pow(x - 1, 3)*pow(x + 1, 5) + (49.0/16.0)*pow(x - 1, 2)*pow(x + 1, 6) + (1.0/4.0)*(x - 1)*pow(x + 1, 7) + (1.0/256.0)*pow(x + 1, 8));
  if (d >= 9)
    /* 9 */ vals.push_back((1.0/512.0)*pow(x - 1, 9) + (81.0/512.0)*pow(x - 1, 8)*(x + 1) + (81.0/32.0)*pow(x - 1, 7)*pow(x + 1, 2) + (441.0/32.0)*pow(x - 1, 6)*pow(x + 1, 3) + (3969.0/128.0)*pow(x - 1, 5)*pow(x + 1, 4) + (3969.0/128.0)*pow(x - 1, 4)*pow(x + 1, 5) + (441.0/32.0)*pow(x - 1, 3)*pow(x + 1, 6) + (81.0/32.0)*pow(x - 1, 2)*pow(x + 1, 7) + (81.0/512.0)*(x - 1)*pow(x + 1, 8) + (1.0/512.0)*pow(x + 1, 9));
  if (d >= 10)
    /* 10 */ vals.push_back((1.0/1024.0)*pow(x - 1, 10) + (25.0/256.0)*pow(x - 1, 9)*(x + 1) + (2025.0/1024.0)*pow(x - 1, 8)*pow(x + 1, 2) + (225.0/16.0)*pow(x - 1, 7)*pow(x + 1, 3) + (11025.0/256.0)*pow(x - 1, 6)*pow(x + 1, 4) + (3969.0/64.0)*pow(x - 1, 5)*pow(x + 1, 5) + (11025.0/256.0)*pow(x - 1, 4)*pow(x + 1, 6) + (225.0/16.0)*pow(x - 1, 3)*pow(x + 1, 7) + (2025.0/1024.0)*pow(x - 1, 2)*pow(x + 1, 8) + (25.0/256.0)*(x - 1)*pow(x + 1, 9) + (1.0/1024.0)*pow(x + 1, 10));
  if (d >= 11)
    /* 11 */ vals.push_back((1.0/2048.0)*pow(x - 1, 11) + (121.0/2048.0)*pow(x - 1, 10)*(x + 1) + (3025.0/2048.0)*pow(x - 1, 9)*pow(x + 1, 2) + (27225.0/2048.0)*pow(x - 1, 8)*pow(x + 1, 3) + (27225.0/512.0)*pow(x - 1, 7)*pow(x + 1, 4) + (53361.0/512.0)*pow(x - 1, 6)*pow(x + 1, 5) + (53361.0/512.0)*pow(x - 1, 5)*pow(x + 1, 6) + (27225.0/512.0)*pow(x - 1, 4)*pow(x + 1, 7) + (27225.0/2048.0)*pow(x - 1, 3)*pow(x + 1, 8) + (3025.0/2048.0)*pow(x - 1, 2)*pow(x + 1, 9) + (121.0/2048.0)*(x - 1)*pow(x + 1, 10) + (1.0/2048.0)*pow(x + 1, 11));
  if (d >= 12)
    /* 12 */ vals.push_back((1.0/4096.0)*pow(x - 1, 12) + (9.0/256.0)*pow(x - 1, 11)*(x + 1) + (1089.0/1024.0)*pow(x - 1, 10)*pow(x + 1, 2) + (3025.0/256.0)*pow(x - 1, 9)*pow(x + 1, 3) + (245025.0/4096.0)*pow(x - 1, 8)*pow(x + 1, 4) + (9801.0/64.0)*pow(x - 1, 7)*pow(x + 1, 5) + (53361.0/256.0)*pow(x - 1, 6)*pow(x + 1, 6) + (9801.0/64.0)*pow(x - 1, 5)*pow(x + 1, 7) + (245025.0/4096.0)*pow(x - 1, 4)*pow(x + 1, 8) + (3025.0/256.0)*pow(x - 1, 3)*pow(x + 1, 9) + (1089.0/1024.0)*pow(x - 1, 2)*pow(x + 1, 10) + (9.0/256.0)*(x - 1)*pow(x + 1, 11) + (1.0/4096.0)*pow(x + 1, 12));
  if (d >= 13)
    /* 13 */ vals.push_back((1.0/8192.0)*pow(x - 1, 13) + (169.0/8192.0)*pow(x - 1, 12)*(x + 1) + (1521.0/2048.0)*pow(x - 1, 11)*pow(x + 1, 2) + (20449.0/2048.0)*pow(x - 1, 10)*pow(x + 1, 3) + (511225.0/8192.0)*pow(x - 1, 9)*pow(x + 1, 4) + (1656369.0/8192.0)*pow(x - 1, 8)*pow(x + 1, 5) + (184041.0/512.0)*pow(x - 1, 7)*pow(x + 1, 6) + (184041.0/512.0)*pow(x - 1, 6)*pow(x + 1, 7) + (1656369.0/8192.0)*pow(x - 1, 5)*pow(x + 1, 8) + (511225.0/8192.0)*pow(x - 1, 4)*pow(x + 1, 9) + (20449.0/2048.0)*pow(x - 1, 3)*pow(x + 1, 10) + (1521.0/2048.0)*pow(x - 1, 2)*pow(x + 1, 11) + (169.0/8192.0)*(x - 1)*pow(x + 1, 12) + (1.0/8192.0)*pow(x + 1, 13));
  if (d >= 14)
    /* 14 */ vals.push_back((1.0/16384.0)*pow(x - 1, 14) + (49.0/4096.0)*pow(x - 1, 13)*(x + 1) + (8281.0/16384.0)*pow(x - 1, 12)*pow(x + 1, 2) + (8281.0/1024.0)*pow(x - 1, 11)*pow(x + 1, 3) + (1002001.0/16384.0)*pow(x - 1, 10)*pow(x + 1, 4) + (1002001.0/4096.0)*pow(x - 1, 9)*pow(x + 1, 5) + (9018009.0/16384.0)*pow(x - 1, 8)*pow(x + 1, 6) + (184041.0/256.0)*pow(x - 1, 7)*pow(x + 1, 7) + (9018009.0/16384.0)*pow(x - 1, 6)*pow(x + 1, 8) + (1002001.0/4096.0)*pow(x - 1, 5)*pow(x + 1, 9) + (1002001.0/16384.0)*pow(x - 1, 4)*pow(x + 1, 10) + (8281.0/1024.0)*pow(x - 1, 3)*pow(x + 1, 11) + (8281.0/16384.0)*pow(x - 1, 2)*pow(x + 1, 12) + (49.0/4096.0)*(x - 1)*pow(x + 1, 13) + (1.0/16384.0)*pow(x + 1, 14));
  if (d >= 15)
    /* 15 */ vals.push_back((1.0/32768.0)*pow(x - 1, 15) + (225.0/32768.0)*pow(x - 1, 14)*(x + 1) + (11025.0/32768.0)*pow(x - 1, 13)*pow(x + 1, 2) + (207025.0/32768.0)*pow(x - 1, 12)*pow(x + 1, 3) + (1863225.0/32768.0)*pow(x - 1, 11)*pow(x + 1, 4) + (9018009.0/32768.0)*pow(x - 1, 10)*pow(x + 1, 5) + (25050025.0/32768.0)*pow(x - 1, 9)*pow(x + 1, 6) + (41409225.0/32768.0)*pow(x - 1, 8)*pow(x + 1, 7) + (41409225.0/32768.0)*pow(x - 1, 7)*pow(x + 1, 8) + (25050025.0/32768.0)*pow(x - 1, 6)*pow(x + 1, 9) + (9018009.0/32768.0)*pow(x - 1, 5)*pow(x + 1, 10) + (1863225.0/32768.0)*pow(x - 1, 4)*pow(x + 1, 11) + (207025.0/32768.0)*pow(x - 1, 3)*pow(x + 1, 12) + (11025.0/32768.0)*pow(x - 1, 2)*pow(x + 1, 13) + (225.0/32768.0)*(x - 1)*pow(x + 1, 14) + (1.0/32768.0)*pow(x + 1, 15));
  if (d >= 16)
    /* 16 */ vals.push_back((1.0/65536.0)*pow(x - 1, 16) + (1.0/256.0)*pow(x - 1, 15)*(x + 1) + (225.0/1024.0)*pow(x - 1, 14)*pow(x + 1, 2) + (1225.0/256.0)*pow(x - 1, 13)*pow(x + 1, 3) + (207025.0/4096.0)*pow(x - 1, 12)*pow(x + 1, 4) + (74529.0/256.0)*pow(x - 1, 11)*pow(x + 1, 5) + (1002001.0/1024.0)*pow(x - 1, 10)*pow(x + 1, 6) + (511225.0/256.0)*pow(x - 1, 9)*pow(x + 1, 7) + (41409225.0/16384.0)*pow(x - 1, 8)*pow(x + 1, 8) + (511225.0/256.0)*pow(x - 1, 7)*pow(x + 1, 9) + (1002001.0/1024.0)*pow(x - 1, 6)*pow(x + 1, 10) + (74529.0/256.0)*pow(x - 1, 5)*pow(x + 1, 11) + (207025.0/4096.0)*pow(x - 1, 4)*pow(x + 1, 12) + (1225.0/256.0)*pow(x - 1, 3)*pow(x + 1, 13) + (225.0/1024.0)*pow(x - 1, 2)*pow(x + 1, 14) + (1.0/256.0)*(x - 1)*pow(x + 1, 15) + (1.0/65536.0)*pow(x + 1, 16));
  if (d >= 17)
    /* 17 */ vals.push_back((1.0/131072.0)*pow(x - 1, 17) + (289.0/131072.0)*pow(x - 1, 16)*(x + 1) + (289.0/2048.0)*pow(x - 1, 15)*pow(x + 1, 2) + (7225.0/2048.0)*pow(x - 1, 14)*pow(x + 1, 3) + (354025.0/8192.0)*pow(x - 1, 13)*pow(x + 1, 4) + (2393209.0/8192.0)*pow(x - 1, 12)*pow(x + 1, 5) + (2393209.0/2048.0)*pow(x - 1, 11)*pow(x + 1, 6) + (5909761.0/2048.0)*pow(x - 1, 10)*pow(x + 1, 7) + (147744025.0/32768.0)*pow(x - 1, 9)*pow(x + 1, 8) + (147744025.0/32768.0)*pow(x - 1, 8)*pow(x + 1, 9) + (5909761.0/2048.0)*pow(x - 1, 7)*pow(x + 1, 10) + (2393209.0/2048.0)*pow(x - 1, 6)*pow(x + 1, 11) + (2393209.0/8192.0)*pow(x - 1, 5)*pow(x + 1, 12) + (354025.0/8192.0)*pow(x - 1, 4)*pow(x + 1, 13) + (7225.0/2048.0)*pow(x - 1, 3)*pow(x + 1, 14) + (289.0/2048.0)*pow(x - 1, 2)*pow(x + 1, 15) + (289.0/131072.0)*(x - 1)*pow(x + 1, 16) + (1.0/131072.0)*pow(x + 1, 17));
  if (d >= 18)
    /* 18 */ vals.push_back((1.0/262144.0)*pow(x - 1, 18) + (81.0/65536.0)*pow(x - 1, 17)*(x + 1) + (23409.0/262144.0)*pow(x - 1, 16)*pow(x + 1, 2) + (2601.0/1024.0)*pow(x - 1, 15)*pow(x + 1, 3) + (585225.0/16384.0)*pow(x - 1, 14)*pow(x + 1, 4) + (1147041.0/4096.0)*pow(x - 1, 13)*pow(x + 1, 5) + (21538881.0/16384.0)*pow(x - 1, 12)*pow(x + 1, 6) + (3956121.0/1024.0)*pow(x - 1, 11)*pow(x + 1, 7) + (478690641.0/65536.0)*pow(x - 1, 10)*pow(x + 1, 8) + (147744025.0/16384.0)*pow(x - 1, 9)*pow(x + 1, 9) + (478690641.0/65536.0)*pow(x - 1, 8)*pow(x + 1, 10) + (3956121.0/1024.0)*pow(x - 1, 7)*pow(x + 1, 11) + (21538881.0/16384.0)*pow(x - 1, 6)*pow(x + 1, 12) + (1147041.0/4096.0)*pow(x - 1, 5)*pow(x + 1, 13) + (585225.0/16384.0)*pow(x - 1, 4)*pow(x + 1, 14) + (2601.0/1024.0)*pow(x - 1, 3)*pow(x + 1, 15) + (23409.0/262144.0)*pow(x - 1, 2)*pow(x + 1, 16) + (81.0/65536.0)*(x - 1)*pow(x + 1, 17) + (1.0/262144.0)*pow(x + 1, 18));
  if (d >= 19)
    /* 19 */ vals.push_back((1.0/524288.0)*pow(x - 1, 19) + (361.0/524288.0)*pow(x - 1, 18)*(x + 1) + (29241.0/524288.0)*pow(x - 1, 17)*pow(x + 1, 2) + (938961.0/524288.0)*pow(x - 1, 16)*pow(x + 1, 3) + (938961.0/32768.0)*pow(x - 1, 15)*pow(x + 1, 4) + (8450649.0/32768.0)*pow(x - 1, 14)*pow(x + 1, 5) + (46009089.0/32768.0)*pow(x - 1, 13)*pow(x + 1, 6) + (158684409.0/32768.0)*pow(x - 1, 12)*pow(x + 1, 7) + (1428159681.0/131072.0)*pow(x - 1, 11)*pow(x + 1, 8) + (2133423721.0/131072.0)*pow(x - 1, 10)*pow(x + 1, 9) + (2133423721.0/131072.0)*pow(x - 1, 9)*pow(x + 1, 10) + (1428159681.0/131072.0)*pow(x - 1, 8)*pow(x + 1, 11) + (158684409.0/32768.0)*pow(x - 1, 7)*pow(x + 1, 12) + (46009089.0/32768.0)*pow(x - 1, 6)*pow(x + 1, 13) + (8450649.0/32768.0)*pow(x - 1, 5)*pow(x + 1, 14) + (938961.0/32768.0)*pow(x - 1, 4)*pow(x + 1, 15) + (938961.0/524288.0)*pow(x - 1, 3)*pow(x + 1, 16) + (29241.0/524288.0)*pow(x - 1, 2)*pow(x + 1, 17) + (361.0/524288.0)*(x - 1)*pow(x + 1, 18) + (1.0/524288.0)*pow(x + 1, 19));
  if (d >= 20)
    /* 20 */ vals.push_back((1.0/1048576.0)*pow(x - 1, 20) + (25.0/65536.0)*pow(x - 1, 19)*(x + 1) + (9025.0/262144.0)*pow(x - 1, 18)*pow(x + 1, 2) + (81225.0/65536.0)*pow(x - 1, 17)*pow(x + 1, 3) + (23474025.0/1048576.0)*pow(x - 1, 16)*pow(x + 1, 4) + (938961.0/4096.0)*pow(x - 1, 15)*pow(x + 1, 5) + (23474025.0/16384.0)*pow(x - 1, 14)*pow(x + 1, 6) + (23474025.0/4096.0)*pow(x - 1, 13)*pow(x + 1, 7) + (3967110225.0/262144.0)*pow(x - 1, 12)*pow(x + 1, 8) + (440790025.0/16384.0)*pow(x - 1, 11)*pow(x + 1, 9) + (2133423721.0/65536.0)*pow(x - 1, 10)*pow(x + 1, 10) + (440790025.0/16384.0)*pow(x - 1, 9)*pow(x + 1, 11) + (3967110225.0/262144.0)*pow(x - 1, 8)*pow(x + 1, 12) + (23474025.0/4096.0)*pow(x - 1, 7)*pow(x + 1, 13) + (23474025.0/16384.0)*pow(x - 1, 6)*pow(x + 1, 14) + (938961.0/4096.0)*pow(x - 1, 5)*pow(x + 1, 15) + (23474025.0/1048576.0)*pow(x - 1, 4)*pow(x + 1, 16) + (81225.0/65536.0)*pow(x - 1, 3)*pow(x + 1, 17) + (9025.0/262144.0)*pow(x - 1, 2)*pow(x + 1, 18) + (25.0/65536.0)*(x - 1)*pow(x + 1, 19) + (1.0/1048576.0)*pow(x + 1, 20));
  if (d >= 21)
    /* 21 */ vals.push_back((1.0/2097152.0)*pow(x - 1, 21) + (441.0/2097152.0)*pow(x - 1, 20)*(x + 1) + (11025.0/524288.0)*pow(x - 1, 19)*pow(x + 1, 2) + (442225.0/524288.0)*pow(x - 1, 18)*pow(x + 1, 3) + (35820225.0/2097152.0)*pow(x - 1, 17)*pow(x + 1, 4) + (414081801.0/2097152.0)*pow(x - 1, 16)*pow(x + 1, 5) + (46009089.0/32768.0)*pow(x - 1, 15)*pow(x + 1, 6) + (211266225.0/32768.0)*pow(x - 1, 14)*pow(x + 1, 7) + (10352045025.0/524288.0)*pow(x - 1, 13)*pow(x + 1, 8) + (21598711225.0/524288.0)*pow(x - 1, 12)*pow(x + 1, 9) + (7775536041.0/131072.0)*pow(x - 1, 11)*pow(x + 1, 10) + (7775536041.0/131072.0)*pow(x - 1, 10)*pow(x + 1, 11) + (21598711225.0/524288.0)*pow(x - 1, 9)*pow(x + 1, 12) + (10352045025.0/524288.0)*pow(x - 1, 8)*pow(x + 1, 13) + (211266225.0/32768.0)*pow(x - 1, 7)*pow(x + 1, 14) + (46009089.0/32768.0)*pow(x - 1, 6)*pow(x + 1, 15) + (414081801.0/2097152.0)*pow(x - 1, 5)*pow(x + 1, 16) + (35820225.0/2097152.0)*pow(x - 1, 4)*pow(x + 1, 17) + (442225.0/524288.0)*pow(x - 1, 3)*pow(x + 1, 18) + (11025.0/524288.0)*pow(x - 1, 2)*pow(x + 1, 19) + (441.0/2097152.0)*(x - 1)*pow(x + 1, 20) + (1.0/2097152.0)*pow(x + 1, 21));
  if (d >= 22)
    /* 22 */ vals.push_back((1.0/4194304.0)*pow(x - 1, 22) + (121.0/1048576.0)*pow(x - 1, 21)*(x + 1) + (53361.0/4194304.0)*pow(x - 1, 20)*pow(x + 1, 2) + (148225.0/262144.0)*pow(x - 1, 19)*pow(x + 1, 3) + (53509225.0/4194304.0)*pow(x - 1, 18)*pow(x + 1, 4) + (173369889.0/1048576.0)*pow(x - 1, 17)*pow(x + 1, 5) + (5567099769.0/4194304.0)*pow(x - 1, 16)*pow(x + 1, 6) + (113614281.0/16384.0)*pow(x - 1, 15)*pow(x + 1, 7) + (25563213225.0/1048576.0)*pow(x - 1, 14)*pow(x + 1, 8) + (15464166025.0/262144.0)*pow(x - 1, 13)*pow(x + 1, 9) + (104537762329.0/1048576.0)*pow(x - 1, 12)*pow(x + 1, 10) + (7775536041.0/65536.0)*pow(x - 1, 11)*pow(x + 1, 11) + (104537762329.0/1048576.0)*pow(x - 1, 10)*pow(x + 1, 12) + (15464166025.0/262144.0)*pow(x - 1, 9)*pow(x + 1, 13) + (25563213225.0/1048576.0)*pow(x - 1, 8)*pow(x + 1, 14) + (113614281.0/16384.0)*pow(x - 1, 7)*pow(x + 1, 15) + (5567099769.0/4194304.0)*pow(x - 1, 6)*pow(x + 1, 16) + (173369889.0/1048576.0)*pow(x - 1, 5)*pow(x + 1, 17) + (53509225.0/4194304.0)*pow(x - 1, 4)*pow(x + 1, 18) + (148225.0/262144.0)*pow(x - 1, 3)*pow(x + 1, 19) + (53361.0/4194304.0)*pow(x - 1, 2)*pow(x + 1, 20) + (121.0/1048576.0)*(x - 1)*pow(x + 1, 21) + (1.0/4194304.0)*pow(x + 1, 22));
  if (d >= 23)
    /* 23 */ vals.push_back((1.0/8388608.0)*pow(x - 1, 23) + (529.0/8388608.0)*pow(x - 1, 22)*(x + 1) + (64009.0/8388608.0)*pow(x - 1, 21)*pow(x + 1, 2) + (3136441.0/8388608.0)*pow(x - 1, 20)*pow(x + 1, 3) + (78411025.0/8388608.0)*pow(x - 1, 19)*pow(x + 1, 4) + (1132255201.0/8388608.0)*pow(x - 1, 18)*pow(x + 1, 5) + (10190296809.0/8388608.0)*pow(x - 1, 17)*pow(x + 1, 6) + (60101954649.0/8388608.0)*pow(x - 1, 16)*pow(x + 1, 7) + (60101954649.0/2097152.0)*pow(x - 1, 15)*pow(x + 1, 8) + (166949874025.0/2097152.0)*pow(x - 1, 14)*pow(x + 1, 9) + (327221753089.0/2097152.0)*pow(x - 1, 13)*pow(x + 1, 10) + (457028729521.0/2097152.0)*pow(x - 1, 12)*pow(x + 1, 11) + (457028729521.0/2097152.0)*pow(x - 1, 11)*pow(x + 1, 12) + (327221753089.0/2097152.0)*pow(x - 1, 10)*pow(x + 1, 13) + (166949874025.0/2097152.0)*pow(x - 1, 9)*pow(x + 1, 14) + (60101954649.0/2097152.0)*pow(x - 1, 8)*pow(x + 1, 15) + (60101954649.0/8388608.0)*pow(x - 1, 7)*pow(x + 1, 16) + (10190296809.0/8388608.0)*pow(x - 1, 6)*pow(x + 1, 17) + (1132255201.0/8388608.0)*pow(x - 1, 5)*pow(x + 1, 18) + (78411025.0/8388608.0)*pow(x - 1, 4)*pow(x + 1, 19) + (3136441.0/8388608.0)*pow(x - 1, 3)*pow(x + 1, 20) + (64009.0/8388608.0)*pow(x - 1, 2)*pow(x + 1, 21) + (529.0/8388608.0)*(x - 1)*pow(x + 1, 22) + (1.0/8388608.0)*pow(x + 1, 23));
  if (d >= 24)
    /* 24 */ vals.push_back((1.0/16777216.0)*pow(x - 1, 24) + (9.0/262144.0)*pow(x - 1, 23)*(x + 1) + (4761.0/1048576.0)*pow(x - 1, 22)*pow(x + 1, 2) + (64009.0/262144.0)*pow(x - 1, 21)*pow(x + 1, 3) + (28227969.0/4194304.0)*pow(x - 1, 20)*pow(x + 1, 4) + (28227969.0/262144.0)*pow(x - 1, 19)*pow(x + 1, 5) + (1132255201.0/1048576.0)*pow(x - 1, 18)*pow(x + 1, 6) + (1871687169.0/262144.0)*pow(x - 1, 17)*pow(x + 1, 7) + (540917591841.0/16777216.0)*pow(x - 1, 16)*pow(x + 1, 8) + (6677994961.0/65536.0)*pow(x - 1, 15)*pow(x + 1, 9) + (60101954649.0/262144.0)*pow(x - 1, 14)*pow(x + 1, 10) + (24338808081.0/65536.0)*pow(x - 1, 13)*pow(x + 1, 11) + (457028729521.0/1048576.0)*pow(x - 1, 12)*pow(x + 1, 12) + (24338808081.0/65536.0)*pow(x - 1, 11)*pow(x + 1, 13) + (60101954649.0/262144.0)*pow(x - 1, 10)*pow(x + 1, 14) + (6677994961.0/65536.0)*pow(x - 1, 9)*pow(x + 1, 15) + (540917591841.0/16777216.0)*pow(x - 1, 8)*pow(x + 1, 16) + (1871687169.0/262144.0)*pow(x - 1, 7)*pow(x + 1, 17) + (1132255201.0/1048576.0)*pow(x - 1, 6)*pow(x + 1, 18) + (28227969.0/262144.0)*pow(x - 1, 5)*pow(x + 1, 19) + (28227969.0/4194304.0)*pow(x - 1, 4)*pow(x + 1, 20) + (64009.0/262144.0)*pow(x - 1, 3)*pow(x + 1, 21) + (4761.0/1048576.0)*pow(x - 1, 2)*pow(x + 1, 22) + (9.0/262144.0)*(x - 1)*pow(x + 1, 23) + (1.0/16777216.0)*pow(x + 1, 24));
  if (d >= 25)
    /* 25 */ vals.push_back((1.0/33554432.0)*pow(x - 1, 25) + (625.0/33554432.0)*pow(x - 1, 24)*(x + 1) + (5625.0/2097152.0)*pow(x - 1, 23)*pow(x + 1, 2) + (330625.0/2097152.0)*pow(x - 1, 22)*pow(x + 1, 3) + (40005625.0/8388608.0)*pow(x - 1, 21)*pow(x + 1, 4) + (705699225.0/8388608.0)*pow(x - 1, 20)*pow(x + 1, 5) + (1960275625.0/2097152.0)*pow(x - 1, 19)*pow(x + 1, 6) + (14442030625.0/2097152.0)*pow(x - 1, 18)*pow(x + 1, 7) + (1169804480625.0/33554432.0)*pow(x - 1, 17)*pow(x + 1, 8) + (4173746850625.0/33554432.0)*pow(x - 1, 16)*pow(x + 1, 9) + (166949874025.0/524288.0)*pow(x - 1, 15)*pow(x + 1, 10) + (310443980625.0/524288.0)*pow(x - 1, 14)*pow(x + 1, 11) + (1690195005625.0/2097152.0)*pow(x - 1, 13)*pow(x + 1, 12) + (1690195005625.0/2097152.0)*pow(x - 1, 12)*pow(x + 1, 13) + (310443980625.0/524288.0)*pow(x - 1, 11)*pow(x + 1, 14) + (166949874025.0/524288.0)*pow(x - 1, 10)*pow(x + 1, 15) + (4173746850625.0/33554432.0)*pow(x - 1, 9)*pow(x + 1, 16) + (1169804480625.0/33554432.0)*pow(x - 1, 8)*pow(x + 1, 17) + (14442030625.0/2097152.0)*pow(x - 1, 7)*pow(x + 1, 18) + (1960275625.0/2097152.0)*pow(x - 1, 6)*pow(x + 1, 19) + (705699225.0/8388608.0)*pow(x - 1, 5)*pow(x + 1, 20) + (40005625.0/8388608.0)*pow(x - 1, 4)*pow(x + 1, 21) + (330625.0/2097152.0)*pow(x - 1, 3)*pow(x + 1, 22) + (5625.0/2097152.0)*pow(x - 1, 2)*pow(x + 1, 23) + (625.0/33554432.0)*(x - 1)*pow(x + 1, 24) + (1.0/33554432.0)*pow(x + 1, 25));
  if (d >= 26)
    /* 26 */ vals.push_back((1.0/67108864.0)*pow(x - 1, 26) + (169.0/16777216.0)*pow(x - 1, 25)*(x + 1) + (105625.0/67108864.0)*pow(x - 1, 24)*pow(x + 1, 2) + (105625.0/1048576.0)*pow(x - 1, 23)*pow(x + 1, 3) + (55875625.0/16777216.0)*pow(x - 1, 22)*pow(x + 1, 4) + (270438025.0/4194304.0)*pow(x - 1, 21)*pow(x + 1, 5) + (13251463225.0/16777216.0)*pow(x - 1, 20)*pow(x + 1, 6) + (6760950625.0/1048576.0)*pow(x - 1, 19)*pow(x + 1, 7) + (2440703175625.0/67108864.0)*pow(x - 1, 18)*pow(x + 1, 8) + (2440703175625.0/16777216.0)*pow(x - 1, 17)*pow(x + 1, 9) + (28214528710225.0/67108864.0)*pow(x - 1, 16)*pow(x + 1, 10) + (233177923225.0/262144.0)*pow(x - 1, 15)*pow(x + 1, 11) + (5829448080625.0/4194304.0)*pow(x - 1, 14)*pow(x + 1, 12) + (1690195005625.0/1048576.0)*pow(x - 1, 13)*pow(x + 1, 13) + (5829448080625.0/4194304.0)*pow(x - 1, 12)*pow(x + 1, 14) + (233177923225.0/262144.0)*pow(x - 1, 11)*pow(x + 1, 15) + (28214528710225.0/67108864.0)*pow(x - 1, 10)*pow(x + 1, 16) + (2440703175625.0/16777216.0)*pow(x - 1, 9)*pow(x + 1, 17) + (2440703175625.0/67108864.0)*pow(x - 1, 8)*pow(x + 1, 18) + (6760950625.0/1048576.0)*pow(x - 1, 7)*pow(x + 1, 19) + (13251463225.0/16777216.0)*pow(x - 1, 6)*pow(x + 1, 20) + (270438025.0/4194304.0)*pow(x - 1, 5)*pow(x + 1, 21) + (55875625.0/16777216.0)*pow(x - 1, 4)*pow(x + 1, 22) + (105625.0/1048576.0)*pow(x - 1, 3)*pow(x + 1, 23) + (105625.0/67108864.0)*pow(x - 1, 2)*pow(x + 1, 24) + (169.0/16777216.0)*(x - 1)*pow(x + 1, 25) + (1.0/67108864.0)*pow(x + 1, 26));
  if (d >= 27)
    /* 27 */ vals.push_back((1.0/134217728.0)*pow(x - 1, 27) + (729.0/134217728.0)*pow(x - 1, 26)*(x + 1) + (123201.0/134217728.0)*pow(x - 1, 25)*pow(x + 1, 2) + (8555625.0/134217728.0)*pow(x - 1, 24)*pow(x + 1, 3) + (77000625.0/33554432.0)*pow(x - 1, 23)*pow(x + 1, 4) + (1629333225.0/33554432.0)*pow(x - 1, 22)*pow(x + 1, 5) + (21905480025.0/33554432.0)*pow(x - 1, 21)*pow(x + 1, 6) + (197149320225.0/33554432.0)*pow(x - 1, 20)*pow(x + 1, 7) + (4928733005625.0/134217728.0)*pow(x - 1, 19)*pow(x + 1, 8) + (21966328580625.0/134217728.0)*pow(x - 1, 18)*pow(x + 1, 9) + (71170904601225.0/134217728.0)*pow(x - 1, 17)*pow(x + 1, 10) + (169986706031025.0/134217728.0)*pow(x - 1, 16)*pow(x + 1, 11) + (18887411781225.0/8388608.0)*pow(x - 1, 15)*pow(x + 1, 12) + (25145962430625.0/8388608.0)*pow(x - 1, 14)*pow(x + 1, 13) + (25145962430625.0/8388608.0)*pow(x - 1, 13)*pow(x + 1, 14) + (18887411781225.0/8388608.0)*pow(x - 1, 12)*pow(x + 1, 15) + (169986706031025.0/134217728.0)*pow(x - 1, 11)*pow(x + 1, 16) + (71170904601225.0/134217728.0)*pow(x - 1, 10)*pow(x + 1, 17) + (21966328580625.0/134217728.0)*pow(x - 1, 9)*pow(x + 1, 18) + (4928733005625.0/134217728.0)*pow(x - 1, 8)*pow(x + 1, 19) + (197149320225.0/33554432.0)*pow(x - 1, 7)*pow(x + 1, 20) + (21905480025.0/33554432.0)*pow(x - 1, 6)*pow(x + 1, 21) + (1629333225.0/33554432.0)*pow(x - 1, 5)*pow(x + 1, 22) + (77000625.0/33554432.0)*pow(x - 1, 4)*pow(x + 1, 23) + (8555625.0/134217728.0)*pow(x - 1, 3)*pow(x + 1, 24) + (123201.0/134217728.0)*pow(x - 1, 2)*pow(x + 1, 25) + (729.0/134217728.0)*(x - 1)*pow(x + 1, 26) + (1.0/134217728.0)*pow(x + 1, 27));
  if (d >= 28)
    /* 28 */ vals.push_back((1.0/268435456.0)*pow(x - 1, 28) + (49.0/16777216.0)*pow(x - 1, 27)*(x + 1) + (35721.0/67108864.0)*pow(x - 1, 26)*pow(x + 1, 2) + (670761.0/16777216.0)*pow(x - 1, 25)*pow(x + 1, 3) + (419225625.0/268435456.0)*pow(x - 1, 24)*pow(x + 1, 4) + (150921225.0/4194304.0)*pow(x - 1, 23)*pow(x + 1, 5) + (8870814225.0/16777216.0)*pow(x - 1, 22)*pow(x + 1, 6) + (21905480025.0/4194304.0)*pow(x - 1, 21)*pow(x + 1, 7) + (9660316691025.0/268435456.0)*pow(x - 1, 20)*pow(x + 1, 8) + (2981579225625.0/16777216.0)*pow(x - 1, 19)*pow(x + 1, 9) + (43054004018025.0/67108864.0)*pow(x - 1, 18)*pow(x + 1, 10) + (28821275417025.0/16777216.0)*pow(x - 1, 17)*pow(x + 1, 11) + (925483177280025.0/268435456.0)*pow(x - 1, 16)*pow(x + 1, 12) + (5476231818225.0/1048576.0)*pow(x - 1, 15)*pow(x + 1, 13) + (25145962430625.0/4194304.0)*pow(x - 1, 14)*pow(x + 1, 14) + (5476231818225.0/1048576.0)*pow(x - 1, 13)*pow(x + 1, 15) + (925483177280025.0/268435456.0)*pow(x - 1, 12)*pow(x + 1, 16) + (28821275417025.0/16777216.0)*pow(x - 1, 11)*pow(x + 1, 17) + (43054004018025.0/67108864.0)*pow(x - 1, 10)*pow(x + 1, 18) + (2981579225625.0/16777216.0)*pow(x - 1, 9)*pow(x + 1, 19) + (9660316691025.0/268435456.0)*pow(x - 1, 8)*pow(x + 1, 20) + (21905480025.0/4194304.0)*pow(x - 1, 7)*pow(x + 1, 21) + (8870814225.0/16777216.0)*pow(x - 1, 6)*pow(x + 1, 22) + (150921225.0/4194304.0)*pow(x - 1, 5)*pow(x + 1, 23) + (419225625.0/268435456.0)*pow(x - 1, 4)*pow(x + 1, 24) + (670761.0/16777216.0)*pow(x - 1, 3)*pow(x + 1, 25) + (35721.0/67108864.0)*pow(x - 1, 2)*pow(x + 1, 26) + (49.0/16777216.0)*(x - 1)*pow(x + 1, 27) + (1.0/268435456.0)*pow(x + 1, 28));
  if (d >= 29)
    /* 29 */ vals.push_back((1.0/536870912.0)*pow(x - 1, 29) + (841.0/536870912.0)*pow(x - 1, 28)*(x + 1) + (41209.0/134217728.0)*pow(x - 1, 27)*pow(x + 1, 2) + (3337929.0/134217728.0)*pow(x - 1, 26)*pow(x + 1, 3) + (564110001.0/536870912.0)*pow(x - 1, 25)*pow(x + 1, 4) + (14102750025.0/536870912.0)*pow(x - 1, 24)*pow(x + 1, 5) + (14102750025.0/33554432.0)*pow(x - 1, 23)*pow(x + 1, 6) + (152252138025.0/33554432.0)*pow(x - 1, 22)*pow(x + 1, 7) + (18422508701025.0/536870912.0)*pow(x - 1, 21)*pow(x + 1, 8) + (100300325150025.0/536870912.0)*pow(x - 1, 20)*pow(x + 1, 9) + (100300325150025.0/134217728.0)*pow(x - 1, 19)*pow(x + 1, 10) + (299243118836025.0/134217728.0)*pow(x - 1, 18)*pow(x + 1, 11) + (2693188069524225.0/536870912.0)*pow(x - 1, 17)*pow(x + 1, 12) + (4605510959127225.0/536870912.0)*pow(x - 1, 16)*pow(x + 1, 13) + (93990019574025.0/8388608.0)*pow(x - 1, 15)*pow(x + 1, 14) + (93990019574025.0/8388608.0)*pow(x - 1, 14)*pow(x + 1, 15) + (4605510959127225.0/536870912.0)*pow(x - 1, 13)*pow(x + 1, 16) + (2693188069524225.0/536870912.0)*pow(x - 1, 12)*pow(x + 1, 17) + (299243118836025.0/134217728.0)*pow(x - 1, 11)*pow(x + 1, 18) + (100300325150025.0/134217728.0)*pow(x - 1, 10)*pow(x + 1, 19) + (100300325150025.0/536870912.0)*pow(x - 1, 9)*pow(x + 1, 20) + (18422508701025.0/536870912.0)*pow(x - 1, 8)*pow(x + 1, 21) + (152252138025.0/33554432.0)*pow(x - 1, 7)*pow(x + 1, 22) + (14102750025.0/33554432.0)*pow(x - 1, 6)*pow(x + 1, 23) + (14102750025.0/536870912.0)*pow(x - 1, 5)*pow(x + 1, 24) + (564110001.0/536870912.0)*pow(x - 1, 4)*pow(x + 1, 25) + (3337929.0/134217728.0)*pow(x - 1, 3)*pow(x + 1, 26) + (41209.0/134217728.0)*pow(x - 1, 2)*pow(x + 1, 27) + (841.0/536870912.0)*(x - 1)*pow(x + 1, 28) + (1.0/536870912.0)*pow(x + 1, 29));
  if (d >= 30)
    /* 30 */ vals.push_back((1.0/1073741824.0)*pow(x - 1, 30) + (225.0/268435456.0)*pow(x - 1, 29)*(x + 1) + (189225.0/1073741824.0)*pow(x - 1, 28)*pow(x + 1, 2) + (1030225.0/67108864.0)*pow(x - 1, 27)*pow(x + 1, 3) + (751034025.0/1073741824.0)*pow(x - 1, 26)*pow(x + 1, 4) + (5076990009.0/268435456.0)*pow(x - 1, 25)*pow(x + 1, 5) + (352568750625.0/1073741824.0)*pow(x - 1, 24)*pow(x + 1, 6) + (64757525625.0/16777216.0)*pow(x - 1, 23)*pow(x + 1, 7) + (34256731055625.0/1073741824.0)*pow(x - 1, 22)*pow(x + 1, 8) + (51173635280625.0/268435456.0)*pow(x - 1, 21)*pow(x + 1, 9) + (902702926350225.0/1073741824.0)*pow(x - 1, 20)*pow(x + 1, 10) + (186508869080625.0/67108864.0)*pow(x - 1, 19)*pow(x + 1, 11) + (7481077970900625.0/1073741824.0)*pow(x - 1, 18)*pow(x + 1, 12) + (3585605418005625.0/268435456.0)*pow(x - 1, 17)*pow(x + 1, 13) + (21147754404155625.0/1073741824.0)*pow(x - 1, 16)*pow(x + 1, 14) + (93990019574025.0/4194304.0)*pow(x - 1, 15)*pow(x + 1, 15) + (21147754404155625.0/1073741824.0)*pow(x - 1, 14)*pow(x + 1, 16) + (3585605418005625.0/268435456.0)*pow(x - 1, 13)*pow(x + 1, 17) + (7481077970900625.0/1073741824.0)*pow(x - 1, 12)*pow(x + 1, 18) + (186508869080625.0/67108864.0)*pow(x - 1, 11)*pow(x + 1, 19) + (902702926350225.0/1073741824.0)*pow(x - 1, 10)*pow(x + 1, 20) + (51173635280625.0/268435456.0)*pow(x - 1, 9)*pow(x + 1, 21) + (34256731055625.0/1073741824.0)*pow(x - 1, 8)*pow(x + 1, 22) + (64757525625.0/16777216.0)*pow(x - 1, 7)*pow(x + 1, 23) + (352568750625.0/1073741824.0)*pow(x - 1, 6)*pow(x + 1, 24) + (5076990009.0/268435456.0)*pow(x - 1, 5)*pow(x + 1, 25) + (751034025.0/1073741824.0)*pow(x - 1, 4)*pow(x + 1, 26) + (1030225.0/67108864.0)*pow(x - 1, 3)*pow(x + 1, 27) + (189225.0/1073741824.0)*pow(x - 1, 2)*pow(x + 1, 28) + (225.0/268435456.0)*(x - 1)*pow(x + 1, 29) + (1.0/1073741824.0)*pow(x + 1, 30));
}


void Legendre::orthogonality_coeffs(unsigned d,
                                    std::vector<mpq_class> & coeffs)
{
  coeffs.clear();

  // The ith coefficient is 2/(2*i+1)
  for (unsigned i=0; i<d+1; ++i)
    {
      std::ostringstream oss;
      oss << "2/" << 2*i+1;
      coeffs.push_back(mpq_class(oss.str()));
    }
}


void Legendre::build_H1_projection_matrix(unsigned d,
                                          Matrix<mpfr_class> & matrix)
{
  // Get the "orthogonality coeffs", which are int(phi_i * phi_j) for
  // the requested value of d.
  std::vector<mpq_class> coeffs;
  this->orthogonality_coeffs(d, coeffs);

  // The number of rows/cols in the matrix
  const unsigned N = coeffs.size();

  // Resize the input matrix.
  matrix.resize(coeffs.size(), coeffs.size());

  // Fill in the diagonal entries
  for (unsigned i=0; i<N; ++i)
    matrix(i,i) = coeffs[i];

  // Fill in the off-diagonal parts of the matrix.  These were
  // pre-computed in Python for the reference element and the Legendre polynomials.
  for (unsigned i=0; i<N; ++i)
    for (unsigned j=0; j<N; ++j)
      {
        // The upper triangle is empty
        if (j > i)
          matrix(i,j) += laplace_matrix[j][i];
        else
          matrix(i,j) += laplace_matrix[i][j];
      }
}


const unsigned Legendre::laplace_matrix[31][31] =
  {
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 132, 0, 182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 156, 0, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 132, 0, 182, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 156, 0, 210, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 132, 0, 182, 0, 240, 0, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 156, 0, 210, 0, 272, 0, 342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 132, 0, 182, 0, 240, 0, 306, 0, 380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 156, 0, 210, 0, 272, 0, 342, 0, 420, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 132, 0, 182, 0, 240, 0, 306, 0, 380, 0, 462, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 156, 0, 210, 0, 272, 0, 342, 0, 420, 0, 506, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 132, 0, 182, 0, 240, 0, 306, 0, 380, 0, 462, 0, 552, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 156, 0, 210, 0, 272, 0, 342, 0, 420, 0, 506, 0, 600, 0, 0, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 132, 0, 182, 0, 240, 0, 306, 0, 380, 0, 462, 0, 552, 0, 650, 0, 0, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 156, 0, 210, 0, 272, 0, 342, 0, 420, 0, 506, 0, 600, 0, 702, 0, 0, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 132, 0, 182, 0, 240, 0, 306, 0, 380, 0, 462, 0, 552, 0, 650, 0, 756, 0, 0, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 156, 0, 210, 0, 272, 0, 342, 0, 420, 0, 506, 0, 600, 0, 702, 0, 812, 0, 0},
    {0, 2, 0, 12, 0, 30, 0, 56, 0, 90, 0, 132, 0, 182, 0, 240, 0, 306, 0, 380, 0, 462, 0, 552, 0, 650, 0, 756, 0, 870, 0},
    {0, 0, 6, 0, 20, 0, 42, 0, 72, 0, 110, 0, 156, 0, 210, 0, 272, 0, 342, 0, 420, 0, 506, 0, 600, 0, 702, 0, 812, 0, 930}
  };
